#include <iostream>

#include <stdlib.h>

#include "neiderra/core/io/IOStream.h"

#include "Logger.h"
#include "CommonFunctions.h"
#include "neiderra/core/Environment.h"
#include "neiderra/core/iException.h"

// #include "events.h"
// #include "CoreEventManager.h"

// using neiderra::core::events::sysShutDownEvent;
// using neiderra::core::CoreEventManager;

//CoreLogger blog;
using namespace neiderra::utils;
using namespace neiderra::core;

Logger::Logger(Core* _core): Base(_core) {
	//_out = core->createOutputStream();
	//_out->open("std.log");
	depth=0;
	
	exportMembers();
}

Logger::~Logger() {
}

void Logger::log(float number)
{
	int sign, decimal;
	int precision = 10;
//	log(_fcvt(number, precision, &decimal, &sign));
}

void Logger::log(int number)
{
	char buf[10];
	itoa(number, buf, 10);
	log(buf);
}

void Logger::log(double number)
{
	int sign, decimal;
	int precision = 10;
//	log(_ecvt(number, precision, &decimal, &sign));
}

/*CoreLogger& CoreLogger::operator<<(CoreLogger&, const char* s){
	log(s);
	return *this;
}

const CoreLogger& CoreLogger::operator<<(const std::string& s){
	log(s);
	return *this;
}*/

// #include <iostream>
// 
// using std::cout;
// using std::endl;

void Logger::log(const char* str){
	int i=0;
	for(;str[i]!='\0';i++);	//platform dependent '\0' ?

	//char* buf = new char[depth];
	char buf[64];
	int j;
	for(j=0;j<depth;j++) buf[j]='\t';
	buf[j]='\0';
	std::string indent(buf);

	getOutputStream()->writeln((indent+str).c_str());
//	_out->writeln((intend+str).c_str(), intend.length()+i);
//	char nl[2] = {0x0d, 0x0a};
//	_out->write(nl, 2);	//writeln !!!
}

void Logger::log(const std::string& str){
	log(str.c_str());
}

void Logger::traceBlock(const char* blockName){
	log(std::string(blockName)+std::string(" ->"));
	_blocks.push(blockName);
	depth++;
}

void Logger::leaveBlock()
{
	if(depth > 0) 
	{
		string blockname = _blocks.top();
		depth--;
		log(blockname + "<-");	// + last blockName
		_blocks.pop();
	}
	
	else
		warning("trace depth <= 0");
	
}

void Logger::warning(const std::string& msg)
{
	log("WARNING!!! " + msg);
}

void Logger::fatal(const char* str)
{
  	std::string msg = std::string("fatal error: ")+std::string(str);
	log(msg);
}

/*void neiderra::core::init_logger(core* core, iOutputStream* output)
{
	blog.setCore(core);

	std::cout << "here\n";
	blog.setOutput(output);
	blog.log("Blog init");

}*/

void Logger::executeMethod(const string& name, const list<string>& args)
{
	string logstr = args.front();
	core->getLogger()->log(logstr);
}

void Logger::exportMembers()
{
	core->getEnvironment()->registerMethod("log", this);
}

// void neiderra::core::assert(bool exp, const string& s)
// {
// 	if(!exp)
// 		core::defCoreLogger->log(s);
// }
